home *** CD-ROM | disk | FTP | other *** search
/ Scene 96 / Scene 96 International Edition (Zyklop Software) (Disc 2) (1997).iso / misc / coding / midas060 / samples / dos / demo.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-01-16  |  9.3 KB  |  350 lines

  1. /*      DEMO.C
  2.  *
  3.  * MIDAS megademo
  4.  *
  5.  * Copyright 1996 Petteri Kangaslampi
  6. */
  7.  
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <malloc.h>
  11. #include <string.h>
  12. #include <conio.h>
  13. #include <math.h>
  14. #include "midas.h"
  15. #include "mconfig.h"
  16. #include "vga.h"
  17.  
  18.  
  19. /* Some changes to demo behaviour for Assembly '96. The rules state that the
  20.    demo must start without a configuration screen if either GUS or SB has been
  21.    detected, and this does exactly that. In addition, if the user specifies
  22.    _any_ command line arguments, the config will be run. Feel free to modify
  23.    main(). To get the old behaviour, ie. a config screen always, comment out
  24.    the next line: */
  25. #define ASM96
  26.  
  27.  
  28. /* Music playing position information - updated by UpdateInfo: */
  29. unsigned        position;               /* Current position */
  30. unsigned        pattern;                /* Current pattern number */
  31. unsigned        row;                    /* Current row number */
  32. int             syncInfo;               /* Music synchronization info */
  33.  
  34. /* Music file name ;) */
  35. char            *moduleName = "..\\data\\templsun.xm";
  36.  
  37.  
  38. /* Frame counter variable - note VOLATILE! */
  39. volatile unsigned   frameCount;
  40.  
  41. void CALLING prevr(void)
  42. {
  43.     frameCount++;
  44. }
  45.  
  46.  
  47. /****************************************************************************\
  48. *
  49. * Function:     void Error(char *msg)
  50. *
  51. * Description:  Displays an error message and exits to DOS
  52. *
  53. * Input:        char *msg               error message
  54. *
  55. \****************************************************************************/
  56.  
  57. void Error(char *msg)
  58. {
  59.     vgaSetMode(3);
  60.     printf("Error: %s\n", msg);
  61. #ifndef NOMUSIC
  62.     midasClose();           /* IMPORTANT! */
  63. #endif
  64.     exit(EXIT_FAILURE);
  65. }
  66.  
  67.  
  68.  
  69.  
  70. /****************************************************************************\
  71. *
  72. * Function:     void Errorcode(int errorcode)
  73. *
  74. * Description:  Displays an error message related to a MIDAS error code and
  75. *               exits to DOS
  76. *
  77. * Input:        int errorcode           MIDAS error code
  78. *
  79. \****************************************************************************/
  80.  
  81. void Errorcode(int errorcode)
  82. {
  83.     Error(errorMsg[errorcode]);
  84. }
  85.  
  86.  
  87.  
  88.  
  89. /****************************************************************************\
  90. *
  91. * Function:     void WaitFrame(void)
  92. *
  93. * Description:  Waits for the next frame
  94. *
  95. \****************************************************************************/
  96.  
  97. void WaitFrame(void)
  98. {
  99.     unsigned    old;
  100.  
  101. #ifdef NOMUSIC
  102.     vgaWaitNoVR();
  103.     vgaWaitVR();
  104. #else
  105.  
  106.     /* Playing music - wait for frame counter to change: */
  107.     old = frameCount;
  108.     while ( old == frameCount );
  109. #endif
  110. }
  111.  
  112.  
  113.  
  114.  
  115. /****************************************************************************\
  116. *
  117. * Function:     void UpdateInfo(void)
  118. *
  119. * Description:  Updates song playing information (defined at the beginning of
  120. *               this file)
  121. *
  122. * Note:         To use the position information from Assembler, do the
  123. *               following (almost - get the idea?)
  124. *
  125. *               INCLUDE "midas.inc"
  126. *               ...
  127. *               GLOBAL  UpdateInfo : LANG
  128. *               ...
  129. *               EXTRN   position : dword
  130. *               EXTRN   pattern : dword
  131. *               EXTRN   row : dword
  132. *               EXTRN   syncInfo : dword
  133. *               ...
  134. *               CODESEG
  135. *               ...
  136. *               PROC    SuperRoutine    NEAR
  137. *               ...
  138. *               call    UpdateInfo C
  139. *               cmp     [position],17
  140. *               je      @@design
  141. *               ...
  142. *
  143. \****************************************************************************/
  144.  
  145. void CALLING UpdateInfo(void)
  146. {
  147.     static gmpInformation   *info;
  148.     int         error;
  149.  
  150.     /* Get GMP playing information: (this can't fail but let's just play it
  151.        safe) */
  152.     if ( (error = gmpGetInformation(midasPlayHandle, &info)) != OK )
  153.         midasError(error);
  154.  
  155.     /* Store interesting information in easy-to-access variables: */
  156.     position = info->position;
  157.     pattern = info->pattern;
  158.     row = info->row;
  159.     syncInfo = info->syncInfo;
  160. }
  161.  
  162.  
  163.  
  164. /****************************************************************************\
  165. *
  166. * Function:     void SyncCallback(unsigned syncNum, unsigned position,
  167. *                   unsigned row);
  168. *
  169. * Description:  Music synchronization callback function. Called by GMPlayer
  170. *               whenever command 'W' is encountered (XMs and S3Ms).
  171. *
  172. * Input:        unsigned syncNum        synchronization command infobyte
  173. *               unsigned position       current position
  174. *               unsigned row            current row
  175. *
  176. * Notes:        This function is called from inside the music player timer
  177. *               interrupt! Therefore it may not take very much time (more
  178. *               than a few rasterlines maximum) and shouldn't do really
  179. *               much anything...
  180. *
  181. \****************************************************************************/
  182.  
  183. void CALLING SyncCallback(unsigned syncNum, unsigned position, unsigned row)
  184. {
  185.     static      border = 0;
  186.  
  187.     /* Prevent warnings: */
  188.     position = position;
  189.     row = row;
  190.  
  191.     /* Check if the infobyte is interesting - do something only when command
  192.        "W42" is encountered: */
  193.     if ( syncNum == 0x42 )
  194.     {
  195.         /* Yeah, yeah, flash the border! */
  196.         border ^= 1;
  197.         vgaSetBorder(border);
  198.     }
  199. }
  200.  
  201.  
  202.  
  203.  
  204.  
  205. int main(int argc, char *argv[])
  206. {
  207.     static unsigned    sync;            /* Screen synchronization magic */
  208.     int         error;
  209.     static gmpModule   *module;         /* Da module */
  210.     int         configOK;
  211.  
  212.     /* Prevent warnings: */
  213.     argc = argc;
  214.     argv = argv;
  215.  
  216. #ifndef NOMUSIC
  217.     /* Call this first: */
  218.     midasSetDefaults();
  219.  
  220. #ifdef ASM96
  221.     /* Assembly'96 mode - try to detect the sound card: */
  222.     midasDetectSD();
  223.  
  224.     /* If the card detected wasn't a GUS or an SB or there was something on
  225.        the command line, run the config: */
  226.     if ( ((midasSDNumber != 0) && (midasSDNumber != 4)) || (argc > 1) )
  227.         configOK = midasConfig();
  228.     else
  229.         configOK = 1;
  230. #else
  231.     /* Run MIDAS Sound System setup: */
  232.     configOK = midasConfig();
  233. #endif
  234. #endif
  235.  
  236.     /* Check if the user pressed Esc in config - if yes, exit: */
  237.     if ( !configOK )
  238.         return 0;
  239.  
  240.     /* Here we could set up a cool display mode */
  241.     vgaSetMode(0x03);
  242.     /* But we don't */
  243.  
  244. #ifndef NOMUSIC
  245.     /* Get screen synchronization value: (ie. time per frame) */
  246.     if ( (error = tmrGetScrSync(&sync)) != OK )
  247.         midasError(error);
  248.  
  249.     /* Please read timer.txt for more information about this! */
  250. #endif
  251.  
  252.     /* Now we could return to text mode for setup and stuff */
  253.  
  254. #ifndef NOMUSIC
  255.     /* Check if we got proper screen sync: */
  256.     if ( !mSyncScreen )
  257.     {
  258.         printf("Warning! Unable to synchronize to display refresh!\n"
  259.                "This can lead to problems in music output and flickering.\n"
  260.                "This usually happens only when running under Windows 95 - "
  261.                "please consider\nrunning DOS programs in DOS instead.\n"
  262.                "Press Esc to quit or any other key to continue\n");
  263.         if ( getch() == 27 )
  264.             return 0;
  265.     }
  266.  
  267.     /* Now initialize MIDAS Sound System: */
  268.  
  269.     midasInit();
  270.  
  271.     /* Debug stuff: */
  272.     printf("Using %s\n%s, using port %X, IRQ %i and DMA %i\n",
  273.         midasSD->name, midasSD->cardNames[midasSD->cardType-1],
  274.         midasSD->port, midasSD->IRQ, midasSD->DMA);
  275.  
  276.     puts("Loading music");
  277.  
  278.     /* Load the module: (Not too hard to change for PT or ST3 modules ;) */
  279.     if ( (error = gmpLoadXM(moduleName, 1, NULL, &module)) != OK )
  280.         midasError(error);
  281.     /* Hint: Think of the file name extensions... */
  282. #endif
  283.  
  284.     /* Now we could do all our initialization, set up a fancy display mode
  285.        etc. */
  286.  
  287. #ifndef NOMUSIC
  288.     /* Synchronize the timer to screen update and call prevr() just before
  289.        each Vertical Retrace: */
  290.     if ( (error = tmrSyncScr(sync, &prevr, NULL, NULL)) != OK )
  291.         midasError(error);
  292.  
  293.     /* Start playing the module: */
  294.     midasPlayModule(module, 0);
  295.  
  296.     /* Set the music synchronization callback function: */
  297.    if ( (error = gmpSetSyncCallback(midasPlayHandle, &SyncCallback)) != OK )
  298.         midasError(error);
  299. #endif
  300.  
  301.     /* Now run a super demo:
  302.  
  303.        InitCredits();
  304.        do
  305.        {
  306.            RunCredits();
  307.            UpdateInfo();
  308.        } while ( position < 2 );
  309.  
  310.        InitVectors();
  311.        do
  312.            RunVectors();
  313.            UpdateInfo();
  314.        } while ( position < 13 );
  315.  
  316.        Or just wait for a keypress: */
  317.  
  318.     while ( !kbhit() )
  319.     {
  320.         UpdateInfo();
  321.         WaitFrame();
  322.         printf("Pos %02X, Patt %02X, Row %02X", position,
  323.             pattern, row);
  324.         if ( syncInfo != -1 )
  325.             printf(", Sync %02X\r", syncInfo);
  326.         else
  327.             printf("\r");
  328.     }
  329.  
  330.     getch();
  331.  
  332.     /* Uninitialization */
  333.  
  334. #ifndef NOMUSIC
  335.     /* Stop playing module: */
  336.     midasStopModule(module);
  337.  
  338.     /* Deallocate the module: */
  339.     if ( (error = gmpFreeModule(module)) != OK )
  340.         midasError(error);
  341.  
  342.     /* And close MIDAS: */
  343.     midasClose();
  344. #endif
  345.  
  346.     /* End of DEMO - DOS! */
  347.  
  348.     return 0;
  349. }
  350.